<template>
  <div ref="container" class="scene-container"></div>
</template>

<script setup lang="ts">
import { ref, onMounted, onBeforeUnmount } from "vue";
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import * as dat from "dat.gui";
// import { useMouse } from "@vueuse/core";
import * as CANNON from "cannon-es";
console.log("CANNON", CANNON);

onMounted(() => {});
/**
 * 认识point
 */
// 给当前组件定义名称
defineOptions({
  name: "ThreeScene",
});

const container = ref<HTMLElement>();
let scene: THREE.Scene;
let camera: THREE.PerspectiveCamera;
let renderer: THREE.WebGLRenderer;
let controls: OrbitControls;
let sphere: THREE.Mesh;
let plane: THREE.Mesh;
let spotLight: THREE.SpotLight;
let smallBall: THREE.Mesh;
let points: THREE.Points;
let cubeGroup: THREE.Group;
let sjxGroup: THREE.Group;
let smallBallGroup: THREE.Group;
let shadowGroup: THREE.Group;
//设置时钟
let clock = new THREE.Clock();
let geometry: THREE.BufferGeometry;
let material: THREE.PointsMaterial;
const params = {
  count: 10000,
  size: 0.3,
  radius: 10,
  branch: 5,
  color: "#ff6030",
  rotateScale: 0.3,
  asideColor: "#ffff00",
};
let sphereBody: CANNON.Body;
let world: CANNON.World;
let planeBody: CANNON.Body;
let hitSound = new Audio("/MP3/hit.mp3");
// 初始化场景
const initScene = () => {
  // 创建场景
  scene = new THREE.Scene();
  scene.background = new THREE.Color(0xffccff); // 设置较暗的背景色
  // scene.background = null;
  // 创建相机
  camera = new THREE.PerspectiveCamera(
    75,
    window.innerWidth / window.innerHeight,
    0.1,
    1000
  );
  camera.position.set(0, 0, 20);
  scene.add(camera);

  //创建球
  const sphereGeometry = new THREE.SphereGeometry(1, 20, 20);
  const sphereMaterial = new THREE.MeshStandardMaterial({ color: 0xffffff });
  sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);
  sphere.castShadow = true;
  scene.add(sphere);
  //创建平面
  const floor = new THREE.Mesh(
    new THREE.PlaneGeometry(20, 20),
    new THREE.MeshStandardMaterial({ color: 0xffffff })
  );
  floor.position.set(0, -5, 0);
  floor.rotation.x = -Math.PI / 2;
  floor.receiveShadow = true; // 开启接收阴影
  scene.add(floor);

  //创建物理世界***********************************************************************************
  world = new CANNON.World(); //或者new CANNON.World({gravity:9.82})
  world.gravity.set(0, -9.82, 0);

  //创建物理小球
  //物理小球的形状
  const sphereShape = new CANNON.Sphere(1);
  //设置小球的物理材质
  const sphereWorldMaterial = new CANNON.Material("sphere");
  //物理小球的物体
  sphereBody = new CANNON.Body({
    shape: sphereShape,
    mass: 1, //质量
    position: new CANNON.Vec3(0, 0, 0),
    //物体材质
    material: sphereWorldMaterial,
  });

  world.addBody(sphereBody);

  function hit(e: Event) {
    //获取碰撞强度
    const impactStrength = e.contact.getImpactVelocityAlongNormal();
    if (impactStrength > 2) {
      hitSound.currentTime = 0;
      hitSound.play();
    }

    console.log("碰撞了", impactStrength);
  }
  //添加监听碰撞事件
  sphereBody.addEventListener("collide", hit);

  //创建物理世界的地面
  const planeShape = new CANNON.Plane();
  //设置地面物理材质
  const planeMaterial = new CANNON.Material("floor");
  const planeBody = new CANNON.Body({
    shape: planeShape, //形状
    mass: 0, //质量,质量为0 保持不动
    position: new CANNON.Vec3(0, -5, 0),
    //物体材质
    material: planeMaterial,
    //旋转地面的位置
    // quaternion: new CANNON.Quaternion(1, 0, 0, -Math.PI / 2),
  });

  planeBody.quaternion.setFromAxisAngle(new CANNON.Vec3(1, 0, 0), -Math.PI / 2);
  world.addBody(planeBody);

  //设置2种材质碰撞的参数
  const defaultContactMaterial = new CANNON.ContactMaterial(
    sphereWorldMaterial,
    planeMaterial,
    {
      friction: 0.1, //摩擦力
      restitution: 0.7, //弹性
    }
  );
  //将材料的关联设置添加到物理世界

  world.addContactMaterial(defaultContactMaterial);

  //添加环境光和平行光
  const ambientLight = new THREE.AmbientLight(0xffffff, 0.5);
  scene.add(ambientLight);
  const directionalLight = new THREE.DirectionalLight(0xffffff, 0.5);
  directionalLight.position.set(0, 1, 0);
  directionalLight.castShadow = true; // 开启阴影
  scene.add(directionalLight);

  // generateGalaxy(scene);
  // 创建渲染器
  renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true }); //开启抗锯齿-透明
  renderer.setSize(window.innerWidth, window.innerHeight);
  renderer.shadowMap.enabled = true; // 开启阴影
  renderer.shadowMap.type = THREE.PCFSoftShadowMap;
  container.value?.appendChild(renderer.domElement);
  // 添加坐标轴辅助
  const axesHelper = new THREE.AxesHelper(10);
  scene.add(axesHelper);

  // 添加聚光灯辅助
  // const spotLightHelper = new THREE.SpotLightHelper(spotLight);
  // scene.add(spotLightHelper);

  // 添加轨道控制器
  controls = new OrbitControls(camera, renderer.domElement);
  controls.enableDamping = true;
  controls.dampingFactor = 0.5;

  // 开始动画循环
  animate();
};

// 动画循环函数
const animate = () => {
  // let time = clock.getElapsedTime();
  let deltaTime = clock.getDelta(); //获取时间间隔
  //更新物理引擎里世界的物体
  world.step(1 / 120, deltaTime);
  sphere.position.copy(sphereBody.position);
  requestAnimationFrame(animate);
  controls.update();
  renderer.render(scene, camera);
  // console.log("Rendering frame..."); // 调试信息
};

// 处理窗口大小变化
const handleResize = () => {
  if (camera && renderer) {
    camera.aspect = window.innerWidth / window.innerHeight;
    camera.updateProjectionMatrix();
    renderer.setSize(window.innerWidth, window.innerHeight);
  }
};

// 组件挂载时初始化
onMounted(() => {
  initScene();
  window.addEventListener("resize", handleResize);
});

// 组件卸载时清理
onBeforeUnmount(() => {
  window.removeEventListener("resize", handleResize);
});
</script>

<style scoped>
.scene-container {
  width: 100%;
  height: 100vh;
  overflow: hidden;
  position: fixed;
  top: 0;
  left: 0;
}
</style>
